package com.anabur.bean;

import java.io.File;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.anabur.bean.abstracts.AbstractImportBean;
import com.anabur.bean.table.BalanceTableItem;
import com.anabur.dao.DAOFactory;
import com.anabur.persistent.Balance;
import com.anabur.persistent.Empresa;
import com.anabur.system.AafPropertyReader;
import com.anabur.system.PropertyConstant;


@ManagedBean(name="balanceBean")
@SessionScoped
public class BalanceBean extends AbstractImportBean{
	
	private static final long serialVersionUID = 1L;
	private Map<String, List<String>> propertyMap;
	private Map<Integer, Balance> balanceMap;
	private Map<String, Integer> propertyPositionMap;
	private Integer columnConEncabezados;
	private Integer filaDeTrimestre;
	private Integer caracterComienzoTrimestre;
	private Integer caracterComienzoFechaTrimestre;
	private String formatoFechaTrimestre;
	
	public final static String TAG_ROW = "Row";
	
	private void reloadProperties() throws Exception{
		List<String> patrimonioPropertiesList = new ArrayList<String>();
		List<String> capitalPropertiesList = new ArrayList<String>();
		List<String> gananciaPropertiesList = new ArrayList<String>();
		List<String> resultadoPropertiesList = new ArrayList<String>();
		
		AafPropertyReader propertyReader = new AafPropertyReader();
		boolean foundPropertie = true;
		int iteracion = 1;
		while(foundPropertie){
			if(iteracion == 1){
				String patrimonioProperty = propertyReader.getProperty(PropertyConstant.BALANCE_PATRIMONIO_NETO_PROP);
				patrimonioPropertiesList.add(patrimonioProperty.replaceAll("\uFFFD", " "));
				String capitalProperty = propertyReader.getProperty(PropertyConstant.BALANCE_CAPITAL_SUBSCRIPTO_PROP);
				capitalPropertiesList.add(capitalProperty.replaceAll("\uFFFD", " "));
				String ganaciaProperty = propertyReader.getProperty(PropertyConstant.BALANCE_GANANCIA_PROP);
				gananciaPropertiesList.add(ganaciaProperty.replaceAll("\uFFFD", " "));
				String resultadoProperty = propertyReader.getProperty(PropertyConstant.BALANCE_RESULTADOS_EXTRA_PROP);
				resultadoPropertiesList.add(resultadoProperty.replaceAll("\uFFFD", " "));
			} else {
				try{
					String patrimonioProperty = propertyReader.getProperty(PropertyConstant.BALANCE_PATRIMONIO_NETO_PROP+ "_" + iteracion);
					patrimonioPropertiesList.add(patrimonioProperty.replaceAll("\uFFFD", " "));
					String capitalProperty = propertyReader.getProperty(PropertyConstant.BALANCE_CAPITAL_SUBSCRIPTO_PROP+ "_" + iteracion);
					capitalPropertiesList.add(capitalProperty.replaceAll("\uFFFD", " "));
					String ganaciaProperty = propertyReader.getProperty(PropertyConstant.BALANCE_GANANCIA_PROP+ "_" + iteracion);
					gananciaPropertiesList.add(ganaciaProperty.replaceAll("\uFFFD", " "));
					String resultadoProperty = propertyReader.getProperty(PropertyConstant.BALANCE_RESULTADOS_EXTRA_PROP+ "_" + iteracion);
					resultadoPropertiesList.add(resultadoProperty.replaceAll("\uFFFD", " "));
				}catch (Exception e) {
					foundPropertie = false;
				}
			}
			iteracion++;
		}
		
		propertyMap = new HashMap<String, List<String>>();
		propertyMap.put(Balance.PATRIMONIO_NETO, patrimonioPropertiesList);
		propertyMap.put(Balance.CAPITAL_SUBSCRIPTO, capitalPropertiesList);
		propertyMap.put(Balance.GANANCIA_PERIODO, gananciaPropertiesList);
		propertyMap.put(Balance.RESULTADOS_EXTRA, resultadoPropertiesList);
		
		propertyPositionMap = new HashMap<String, Integer>();
		propertyPositionMap.put(Balance.PATRIMONIO_NETO, -1);
		propertyPositionMap.put(Balance.CAPITAL_SUBSCRIPTO, -1);
		propertyPositionMap.put(Balance.GANANCIA_PERIODO, -1);
		propertyPositionMap.put(Balance.RESULTADOS_EXTRA, -1);
		
		columnConEncabezados = Integer.valueOf(propertyReader.getProperty(PropertyConstant.COLUMNA_ENCABEZADOS_POSICION_PROP));
		filaDeTrimestre = Integer.valueOf(propertyReader.getProperty(PropertyConstant.FILA_DE_TRIMESTRE_PROP));
		caracterComienzoTrimestre = Integer.valueOf(propertyReader.getProperty(PropertyConstant.CARACTER_COMIENZO_TRIMESTRE));
		caracterComienzoFechaTrimestre = Integer.valueOf(propertyReader.getProperty(PropertyConstant.CARACTER_COMIENZO_FECHA_TRIMESTRE)); 
		formatoFechaTrimestre = propertyReader.getProperty(PropertyConstant.FORMATO_FECHA_TRIMESTRE); 
		
	}

	public void importFile(File file){
		balanceMap = new HashMap<Integer, Balance>();
		Boolean isComplete = true;
		String codigoEmpresa = null;
		Empresa empresa = null;
		Integer countImportedRows = 0;
		Integer countNotImportedRows = 0;
		try {
			reloadProperties();// busco las properties
			try{
				codigoEmpresa = file.getName().substring(file.getName().indexOf("_") + 1, file.getName().indexOf("."));
			} catch (Exception e) {
				throw new Exception("Error al buscar el nombre de la empresa despues del _ en el nombre del archivo: " + file.getName());
			}
			DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
			DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
			Document doc = dBuilder.parse(file);
			doc.getDocumentElement().normalize();
			NodeList rowNodeList = doc.getElementsByTagName(TAG_ROW);
			
			setHeaders(rowNodeList);// busco los headers
			validatePropertyPosition(propertyPositionMap); // valido que se encuentre todos
			setData(rowNodeList); // Seteo los datos en el persistente
			
			empresa = DAOFactory.getInstance().getEmpresaDAO().getEmpresaByCodigo(codigoEmpresa);
			if(empresa != null){
				for(Balance balance : balanceMap.values()){
					balance.setEmpresa(empresa);
					if(getReWrite()){
						balance.setID(DAOFactory.getInstance().getBalanceDAO().getBalanceIDPorFechaYEmpresaID(balance.getFechaCierre(), empresa.getID()));
					}
					if(DAOFactory.getInstance().getBalanceDAO().insertOrModify(balance)){
						countImportedRows++;
					} else {
						countNotImportedRows++;
					}
					
				}
			} else  {
				isComplete = false;
			}
			
			BalanceTableItem item = new BalanceTableItem();
			item.setFile(file);
			item.setCodigoEmpresa(codigoEmpresa);
			item.setCountImportedRows(countImportedRows);
			item.setCountNotImportedRows(countNotImportedRows);
			if(isComplete){
				addUploadedFile(item);
				item.setNombreEmpresa(empresa.getNombre());
				item.setNombreRubro(empresa.getRubro().getNombre());
			} else {
				addIncompleteFile(item);
			}
		} catch (Exception e) {
			logErrorInPopupWithoutDetail(e);
		} 
	}
	
	

	
	private void setData(NodeList rowNodeList) throws Exception{
		for(Integer columnPosition: balanceMap.keySet()){
			Balance balance = balanceMap.get(columnPosition);
			String patrimonioNeto = rowNodeList.item(propertyPositionMap.get(Balance.PATRIMONIO_NETO)).getChildNodes().item(columnPosition).getTextContent();
			String capitalSubscripto = rowNodeList.item(propertyPositionMap.get(Balance.CAPITAL_SUBSCRIPTO)).getChildNodes().item(columnPosition).getTextContent();
			String gananciaPeriodo = rowNodeList.item(propertyPositionMap.get(Balance.GANANCIA_PERIODO)).getChildNodes().item(columnPosition).getTextContent();
			String resultadosExtras = "0";
			try{
				resultadosExtras = rowNodeList.item(propertyPositionMap.get(Balance.RESULTADOS_EXTRA)).getChildNodes().item(columnPosition).getTextContent();
			}catch (Exception e) {
				System.out.println("No se encontraron resultados extraordinarios. Se guardara el valor por defecto: 0");
			}
			balance.setPatrimonioNeto(getIsBigdecimal(patrimonioNeto) ? new BigDecimal(patrimonioNeto) : BigDecimal.ZERO);
			balance.setCapitalSuscripto(getIsBigdecimal(capitalSubscripto) ? new BigDecimal(capitalSubscripto) : BigDecimal.ZERO);
			balance.setGanaciaPeriodo(getIsBigdecimal(gananciaPeriodo) ? new BigDecimal(gananciaPeriodo) : BigDecimal.ZERO);
			balance.setResultadosExtraodrinarios(getIsBigdecimal(resultadosExtras) ? new BigDecimal(resultadosExtras) : BigDecimal.ZERO);
		}
	}
		
	private void setHeaders(NodeList rowNodeList) throws Exception{
		for (int i = 0; i < rowNodeList.getLength(); i++) { // itera Rows
			Node rowNode = rowNodeList.item(i);	
			if (rowNode.getNodeType() == Node.ELEMENT_NODE){
				if(i == filaDeTrimestre){ // primera row donde esta el encabezado del trimestre
					parseHeaderColumn(rowNode);
				} else { // resto de los encabezados
					String columnName = rowNode.getChildNodes().item(columnConEncabezados).getTextContent();
					for(String key : propertyMap.keySet()){
						if(columnName != null 
								&& !columnName.equals("")
								&& propertyMap.get(key).contains(columnName)
								&& propertyPositionMap.get(key) == -1){
							propertyPositionMap.put(key, i);
						}
					}
				}
			}
		}
	}
	
	@Override
	protected void parseHeaderColumn(Node rowNode) throws Exception {
		for (int j = 0; j < rowNode.getChildNodes().getLength(); j++) {
			Node cellNode = rowNode.getChildNodes().item(j);
			if (cellNode.getNodeType() == Node.ELEMENT_NODE){
				String trimestre = cellNode.getChildNodes().item(columnConEncabezados).getTextContent();
				if(!trimestre.equals("")
						&& !trimestre.equals("\n")){
					Integer periodo = new Integer(trimestre.substring(caracterComienzoTrimestre,caracterComienzoTrimestre+1)); 
					SimpleDateFormat formatDateTrimestre = new SimpleDateFormat(formatoFechaTrimestre);
					Date fecha = formatDateTrimestre.parse(trimestre.substring(caracterComienzoFechaTrimestre, caracterComienzoFechaTrimestre + formatoFechaTrimestre.length())); 
					Balance balance = new Balance();
					balance.setTrimestre(periodo);
					balance.setFechaCierre(fecha);
					balanceMap.put(j, balance);
				}
			}
		}
	}
}
